#include <iostream>
#include "udp_client.hpp"
#include "utils.hpp"
// #include "protocol.hpp"
#include <csignal>
#include <vector>
#include <unordered_map>
#include "camera_protocol.hpp"
// #include "camera_handle.hpp"
#include "service_camera.hpp"

using namespace gimabl;

#define LOCAL_PORT 1114
#define CAMERA_PORT 55555

static std::string cmaera_ip="192.168.137.63";
static bool g_exit=false;
// static std::mutex g_ackMsgMutex;
// static std::unordered_map<uint16_t, std::unique_ptr<CameraPacket>> g_ackMsgMap;

// static std::mutex g_reqMsgMutex;
// static std::queue<std::unique_ptr<CameraPacket>> g_reqMsgQueue;

void signalHandler( int signum )
{
    std::cout<< "net service process exit!" << std::endl;
    g_exit=true;
    sleep(1);
    exit(signum);
}
#if 0
static void handleAckMsg()
{
    while (!g_exit)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        if(!g_reqMsgQueue.empty())
        {
            std::lock_guard<std::mutex> lock(g_reqMsgMutex);
            auto msgPtr=std::move(g_reqMsgQueue.front());
            g_reqMsgQueue.pop();

            std::cout << "report收到消息(hex): " << GetHexString(msgPtr->getDataBuf(),msgPtr->getDataLen()) << std::endl;
        }

        if(!g_ackMsgMap.empty())
        {
            std::lock_guard<std::mutex> lock(g_ackMsgMutex);
            auto it=g_ackMsgMap.begin();
            while (it!=g_ackMsgMap.end())
            {
                std::cout << "ack收到消息(hex): " << GetHexString(it->second->getDataBuf(),it->second->getDataLen()) << std::endl;
                it=g_ackMsgMap.erase(it);
            }
        }

    }
}

static int32_t ReadMsgHandler(uint8_t* buf,std::size_t size)
{
    // static int32_t num=0;
    // std::cout << num<<"收到消息(hex): " << GetHexString(buf, size) << std::endl;
    // num++;
    auto msgPtr = std::unique_ptr<CameraPacket>(new CameraPacket(size));
    msgPtr->setAckData(buf,size);
    if(msgPtr->ParseData())
    {
        switch (msgPtr->getFlag())
        {
        case Response:
            {
               std::lock_guard<std::mutex> lock(g_ackMsgMutex);
               g_ackMsgMap.insert(std::make_pair(msgPtr->getMsgId(),std::move(msgPtr)));

            }
            break;
        case Status:
        case Report:
            {
                std::lock_guard<std::mutex> lock(g_reqMsgMutex);
                g_reqMsgQueue.push(std::move(msgPtr));
            }
            break;
        
        default:
            break;
        }

    }else
    {
        std::cout << "解析失败" << std::endl;
    }
    return 0;
}



int main(int argc, const char** argv) 
{
    int ret=-1;
    signal(SIGINT, signalHandler); 
    signal(SIGTERM, signalHandler);
    std::cout << "hello world "<< std::endl;

    UdpClient client;
    ret=client.udpInit(cmaera_ip,CAMERA_PORT,LOCAL_PORT);
    if(ret<0)
    {
        std::cout << "udp init failed" << std::endl;
        return ret;
    }

    client.udpRead(ReadMsgHandler,1000);

    std::vector<unsigned char> debugData={0xFE ,0x55 ,0x01 ,0x00 ,0x04 ,0x02 ,0x02 ,0x14 ,0x07 ,0x03 ,0x00 ,0x02 ,0x06 ,0x00 ,0xb7 ,0x00};
    std::vector<unsigned char> debugData1={0xFE,0x55 ,0x01 ,0x00 ,0x04 ,0x01 ,0x02 ,0x1E ,0x29 ,0x02 ,0x00 ,0x03 ,0x64 ,0x00 ,0x00 ,0x49 ,0xde};
    std::vector<unsigned char> debugData2={0xFE,0x55 ,0x01 ,0x00 ,0x04 ,0x01 ,0x02 ,0x1E ,0x29 ,0x02 ,0x00 ,0x03 ,0x0a ,0x00 ,0x00 ,0x1f ,0xcb};

    std::thread th1(handleAckMsg);
    th1.detach();

    // client.udp_write(debugData.data(),debugData.size());
    setImageDisplayMode(client,IMAGE_MODE_ZOOM_VISIBLE);
    sleep(2);
    // setTakePhotoType(client, PHOTO_MODE_TIMER,0x03,0x03);
    // sleep(2);
    // std::string path="/image/";
    // std::string name="test3";
    // takePhoto(client, PHOTO_MODE_ZOOM,CAMERA_CMD_STOP_CAPTURE,path,name);
    // takePhoto(client, PHOTO_MODE_ZOOM,CAMERA_CMD_START_CAPTURE,path,name);

    // // setVisiblePitureResolution(client, PHOTO_RESOLUTION_1920x1080_2M,CAMERA_TYPE_ZOOM);
    // sleep(10);
    // takePhoto(client, PHOTO_MODE_ZOOM,CAMERA_CMD_STOP_CAPTURE,path,name);

    
    // setVisibleRecodeResolution(client, VIDEO_MODE_2K_1920x1440_30P,CAMERA_TYPE_ZOOM);
    // sleep(2);
    // setVisiblePitureSaveFormat(client,IMAGE_FORMAT_JPG);
    // setVisibleVideoSaveFormat(client,VIDEO_FORMAT_MP4);
    // getAllVisibleParams(client,CameraType::CAMERA_ZOOM);
    // sleep(5);
    // setImageDisplayMode(client,IMAGE_MODE_WIDE_VISIBLE);
    // sleep(5);
    // getAllVisibleParams(client,CameraType::CAMERA_WIDE_ANGLE);
    // sleep(10);
    // setImageDisplayMode(client,IMAGE_MODE_ZOOM_VISIBLE);
    // sleep(10);
    // setZoobMode(client,10);
    // sleep(10);
    // setZoobMode(client,2);
    // sleep(10);
    // setZoobMode(client,8);
    // sleep(10);
    // setZoobMode(client,44);

    // sleep(2);
    // std::string path="/root/tmp/";
    // std::string name="test2";
    // takePictures(client,PHOTO_MODE_ZOOM,CAMERA_CMD_START_CAPTURE,path,name);
    // sleep(10);
    // setZoobMode(client,2);
    std::string path1="/video/";
    std::string name1="test3";
    recordVideo(client,VIDEO_MODE_ZOOM,VIDEO_CMD_START_RECORDING,path1,name1);
    sleep(5);
    recordVideo(client,VIDEO_MODE_ZOOM,VIDEO_CMD_STOP_RECORDING,path1,name1);
    // setCameraReproSwitch(client,CAMERA_REPRO_START);
    // sleep(20);
    // setCameraReproSwitch(client,CAMERA_REPRO_STOP);
    // getCameraVersion(client,VISIBLE_CAMERA_VERSION);
    while (!g_exit)
    {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << "main loop" << std::endl;
    }

    client.udpClose();

    return 0;
}

#endif

void test_photoAndRecordFormat(ServiceCamera &camera)
{
    camera.setVisiblePitureSaveFormat(IMAGE_FORMAT_RAW);
    camera.setVisibleRecodeSaveFormat(VIDEO_FORMAT_MOV);
}
void test_photoAndRecord(ServiceCamera &camera)
{
    // 变焦
    camera.setDisplayMode(IMAGE_MODE_ZOOM_VISIBLE);
    camera.switchCameraMode(CAMERA_MODE_PHOTO);
    std::string path="/image/";
    std::string name="zoom";
    camera.takePhoto(PHOTO_MODE_ZOOM,CAMERA_CMD_START_CAPTURE,path,name);
    sleep(2);
    std::string path1="/video/";
    std::string name1="zoom";
    camera.switchCameraMode(CAMERA_MODE_VIDEO);
    camera.recordVideo(VIDEO_MODE_ZOOM,VIDEO_CMD_START_RECORDING,path1,name1);
    sleep(5);
    camera.recordVideo(VIDEO_MODE_ZOOM,VIDEO_CMD_STOP_RECORDING,path1,name1);
    sleep(5);

    //广角
    // camera.setDisplayMode(IMAGE_MODE_WIDE_VISIBLE);
    // camera.switchCameraMode(CAMERA_MODE_PHOTO);
    // sleep(2);
    // std::string name2="wide";
    // camera.takePhoto(PHOTO_MODE_WIDE,CAMERA_CMD_START_CAPTURE,path,name2);
    // sleep(2);
    // camera.switchCameraMode(CAMERA_MODE_VIDEO);
    // camera.recordVideo(VIDEO_MODE_WIDE,VIDEO_CMD_START_RECORDING,path1,name2);
    // sleep(5);
    // camera.recordVideo(VIDEO_MODE_WIDE,VIDEO_CMD_STOP_RECORDING,path1,name2);
}
int main(int argc, const char** argv) 
{
    int ret=-1;
    signal(SIGINT, signalHandler); 
    signal(SIGTERM, signalHandler);
    std::cout << "hello world "<< std::endl;

    ServiceCamera camera;
    ret=camera.InitServiceCamera(single,cmaera_ip,CAMERA_PORT,LOCAL_PORT,1000);
    if(ret<0)
    {
        std::cout << "udp init failed" << std::endl;
        return ret;
    }
    // test_photoAndRecordFormat(camera);
    // test_photoAndRecord(camera);
    camera.setDisplayMode(IMAGE_MODE_ZOOM_VISIBLE);
    camera.getAllVisibleParams(CAMERA_DEFAULT);
    // camera.setVisiblePitureResolution(PHOTO_RESOLUTION_5472x3648_3_2,CAMERA_TYPE_ZOOM);
    // camera.setVisibleRecodeResolution(VIDEO_MODE_4K_3840x2160_60P,CAMERA_TYPE_ZOOM);
    camera.setVideoEncodingFormat(VIDEO_ENCODE_FORMAT_H264);
    // camera.setVisibleVideoResolution(VIDEO_OUTPUT_GIGE_RESET,VIDEO_RESOLUTION_1080P_30FPS);
    camera.getAllVisibleParams(CAMERA_DEFAULT);
    camera.getCameraVersion(VISIBLE_CAMERA_VERSION);

    while (!g_exit)
    {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << "main loop" << std::endl;

    }
    camera.StopServiceCamera();
    return 0;
}


